package com.huiquan.synonymy.service;

import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.huiquan.analysis.domain.User;
import com.huiquan.foundation.util.BusinessUtil;
import com.huiquan.framework.base.BaseService;
import com.huiquan.framework.base.ReturnCode;
import com.huiquan.framework.base.ReturnData;
import com.huiquan.framework.constant.BaseContants;
import com.huiquan.framework.utils.CollectionUtil;
import com.huiquan.framework.utils.ExcelUtil;
import com.huiquan.framework.utils.GetListUtil;
import com.huiquan.framework.utils.RespHeaderUtil;
import com.huiquan.framework.utils.ReturnUtil;
import com.huiquan.icd.dao.IcdDiseaseDao;
import com.huiquan.icd.dao.IcdDiseaseHospitalDao;
import com.huiquan.icd.domain.IcdDisease;
import com.huiquan.icd.service.IcdDiseaseHospitalService;
import com.huiquan.synonymy.dao.SynonymyDao;
import com.huiquan.synonymy.dao.SynonymyWordDao;
import com.huiquan.synonymy.domain.Synonymy;
import com.huiquan.synonymy.domain.SynonymyWord;
import com.huiquan.vocab.constant.VocabConstant;
import com.huiquan.vocab.dao.VocabElementDao;
import com.huiquan.vocab.domain.VocabElement;
import com.huiquan.vocab.service.VocabElementService;

@Service
public class SynonymyService extends BaseService {

	@Autowired
	private SynonymyDao synonymyDao;
	@Autowired
	private IcdDiseaseDao icdDiseaseDao;
	@Autowired
	private SynonymyWordDao synonymyWordDao;
	@Autowired
	private VocabElementDao vocabElementDao;
	@Autowired
	private IcdDiseaseHospitalDao icdDiseaseHospitalDao;
	@Autowired
	private IcdDiseaseHospitalService icdDiseaseHospitalService;

	public ModelAndView list(String startStr, String wordKey, String propertyKey, Integer type, String exactSearchFlag,
			String countPerPageStr) {

		Map<String, Object> param = new HashMap<>();
		// 根据词语查询
		if (wordKey != null && !wordKey.isEmpty()) {
			if (exactSearchFlag != null && exactSearchFlag.equals("1")) {
				param.put("words", "%\t" + wordKey + "\t%");
			} else {
				param.put("words",
						"%" + wordKey.replace(";", "%").replace("；", "%").replace(",", "%").replace("，", "%") + "%");
			}
		}
		// 根据属性查询
		if (propertyKey != null && !propertyKey.isEmpty()) {
			param.put("property", propertyKey);
		}
		param.put("type", type);
		int totalSize = synonymyDao.retrieveSize(param);

		int start = 1;
		if (startStr != null && !startStr.isEmpty()) {
			start = Integer.parseInt(startStr);
		}
		Map<String, Integer> pageNo;
		if (countPerPageStr != null && !countPerPageStr.isEmpty()) {
			int countPerPage = Integer.parseInt(countPerPageStr);
			pageNo = GetListUtil.getPageNoParam(totalSize, startStr, countPerPage);
			param.put("countPerPage", countPerPage);
		} else {
			pageNo = GetListUtil.getPageNoParam(totalSize, startStr);
		}
		int endPage = pageNo.get("endPage");
		start = pageNo.get("start");
		int startIndex = pageNo.get("startIndex");

		List<Synonymy> list = new ArrayList<>();

		if (startIndex < totalSize) {
			param.put("startIndex", startIndex);
			list = synonymyDao.retrieveList(param);

			// 获取同义词的分词列表维护到同义词数据中
			setWordList(list);
		}
		Map<String, String> showSearch = new LinkedHashMap<>();
		showSearch.put("wordKey", "同义词");

		Map<String, String> searchMap = new HashMap<>();
		searchMap.put("wordKey", wordKey);

		Map<String, Object> map = GetListUtil.getReturnMap2(totalSize, start, startIndex, endPage, list, searchMap);
		if (StringUtils.equals("r", propertyKey)) {
			List<String> check = synonymyDao.checkRSynonymyStd();
			map.put("checkR", check);
		}
		map.put("showSearch", showSearch);
		map.put("showSearchValue", searchMap);
		if (Synonymy.TYPE_ELEMENT.equals(type)) {
			map.put("propertyList", VocabConstant.elementProperty);
		}

		LOGGER.info("Get list end!Params:start={},wordKey={},propertyKey={},type={};total size={}",
				new Object[] { start, wordKey, propertyKey, type, totalSize });
		return new ModelAndView("synonymy/index", map);
	}

	private void setWordList(List<Synonymy> list) {
		// 获取同义词的id集
		StringBuilder idsb = new StringBuilder();
		StringBuilder diIdsb = new StringBuilder(); // di的词语集（不在疾病维表可用词中的则置灰）
		for (Synonymy synonymy : list) {
			idsb.append(synonymy.getId());
			idsb.append(",");
			if (synonymy.getProperty().equals(VocabConstant.ELEMENT_DISEASE)) {
				diIdsb.append(synonymy.getId());
				diIdsb.append(",");
			}
		}
		idsb.deleteCharAt(idsb.length() - 1);
		if (diIdsb.length() > 1) {
			diIdsb.deleteCharAt(diIdsb.length() - 1);
		}

		// 根据同义词的id集获取排好序的可用词语和不可用词语
		List<Map<String, Object>> words = synonymyWordDao.retrieveExistElementBySynonymyIds(idsb.toString());
		// 根据排序好的词语遍历，根据ID分好组
		Map<Long, List<String>> existentLists = new HashMap<Long, List<String>>();
		for (Map<String, Object> wordMap : words) {
			List<String> existentList;
			if ((existentList = existentLists.get(((BigInteger) wordMap.get("id")).longValue())) != null) {
				existentList.add((String) wordMap.get("word"));
			} else {
				existentList = new ArrayList<>();
				existentList.add((String) wordMap.get("word"));
				existentLists.put(((BigInteger) wordMap.get("id")).longValue(), existentList);
			}
		}

		// 排除不可用的词语
		List<Map<String, Object>> nonExistWords = new ArrayList<>();
		if (diIdsb.length() > 0) {
			// 获取di词语在疾病表中不存在的词
			nonExistWords = synonymyWordDao.retrieveNonExistDiBySynonymyIds(diIdsb.toString());
		}
		Map<Long, List<String>> nonExistLists = new HashMap<Long, List<String>>();
		if (nonExistWords != null && !nonExistWords.isEmpty()) {
			for (Map<String, Object> wordMap : nonExistWords) {
				Long id = ((BigInteger) wordMap.get("id")).longValue();
				String word = (String) wordMap.get("word");
				// 将可用词语中去除
				existentLists.get(id).remove(word);

				// 维护不可用词
				List<String> nonExistList;
				if ((nonExistList = nonExistLists.get(id)) != null) {
					nonExistList.add((String) wordMap.get("word"));
				} else {
					nonExistList = new ArrayList<>();
					nonExistList.add((String) wordMap.get("word"));
					nonExistLists.put(id, nonExistList);
				}
			}
		}
		// 将可用和不可用的词语列表维护到实体中供前台调用
		// 取英文同义词列表和中文同义词列表
		for (Synonymy synonymy : list) {
			Long id = synonymy.getId();
			List<String> existentList = existentLists.get(id);
			List<String> existentEnglishList = new ArrayList<>();
			List<String> removeList = new ArrayList<>();
			boolean removeFlag = false;
			String regEx = "[\u4E00-\u9FA5]";
			Pattern p = Pattern.compile(regEx);
			if (existentList == null) {
				existentList = new ArrayList<>();
			} else {
				for (String existent : existentList) {
					// 判断是否全英文
					if (!p.matcher(existent).find()) {
						existentEnglishList.add(existent);
						removeList.add(existent);
						removeFlag = true;
					}
				}
				if (removeFlag) {
					existentList.removeAll(removeList);
				}
			}
			List<String> nonExistList = nonExistLists.get(id);
			List<String> nonExistentEnglishList = new ArrayList<>();
			removeList = new ArrayList<>();
			removeFlag = false;
			if (nonExistList == null) {
				nonExistList = new ArrayList<>();
			} else {
				for (String nonExistent : nonExistList) {
					// 判断是否全英文带数字
					if (!p.matcher(nonExistent).find()) {
						nonExistentEnglishList.add(nonExistent);
						removeList.add(nonExistent);
						removeFlag = true;
					}
				}

				if (removeFlag) {
					nonExistList.removeAll(removeList);
				}
			}
			synonymy.setNonExistEnglishWordsList(nonExistentEnglishList);
			synonymy.setEnglishWordsList(existentEnglishList);
			synonymy.setWordsList(existentList);
			synonymy.setNonExistWordsList(nonExistList);
		}
	}

	/**
	 * 预编辑，如果是修改则初始化对应数据
	 */
	public ModelAndView preEdit(String id, int type) {

		Map<String, Object> map = new HashMap<>();
		if (Synonymy.TYPE_ELEMENT.equals(type)) {
			// 返回所有小词属性
			List<String> propertyList = new ArrayList<>(VocabConstant.elementProperty);
			propertyList.add(0, "");
			map.put("propertyList", propertyList);
		}

		if (id == null || id.trim().isEmpty()) {
			map.put("words", new String[] { "", "", "" });
			return new ModelAndView("synonymy/synonymy_edit", map);
		}
		Synonymy synonymy = synonymyDao.retrieveObjectById(Long.parseLong(id));
		String property = synonymy.getProperty();

		List<String> words = synonymyWordDao.retrieveWordListBySynonymyId(synonymy.getId());
		words.add("");

		map.put("id", id);
		map.put("std", synonymy.getStd());
		map.put("chineseStd", synonymy.getChineseStd());
		map.put("englishStd", synonymy.getEnglishStd());
		map.put("property", property);
		map.put("words", words);
		return new ModelAndView("synonymy/synonymy_edit", map);
	}

	private List<Synonymy> checkSynonymyConflict(String id, String property, List<String> wordList,
			List<String> addIdList) {
		List<Synonymy> checkSynonymy = null;
		List<Synonymy> checkSynonymy2 = null;

		if (StringUtils.equalsIgnoreCase(property, "s") || StringUtils.equalsIgnoreCase(property, "si")) {
			Map<String, Object> param = new HashMap<>();
			param.put("list", wordList);
			param.put("sFlag", "1");
			param.put("synonymyId", id);
			// 校验添加的是合并成一个同义词
			checkSynonymy = synonymyDao.checkSynonymyConflict(param);
			Map<String, Object> param2 = new HashMap<>();
			param2.put("list", wordList);
			if (StringUtils.equalsIgnoreCase(property, "s")) {
				param2.put("propertyFlag", "si");
				param2.put("propertyFlag2", "s");
			} else {
				param2.put("propertyFlag", "s");
				param2.put("propertyFlag2", "si");
			}
			param2.put("synonymyId", id);
			checkSynonymy2 = synonymyDao.checkSynonymyConflict2(param2);

		}
		if (StringUtils.equalsIgnoreCase(property, "o") || StringUtils.equalsIgnoreCase(property, "oa")) {
			Map<String, Object> param = new HashMap<>();
			param.put("list", wordList);
			param.put("oFlag", "1");
			param.put("synonymyId", id);
			// 校验添加的是合并成一个同义词
			checkSynonymy = synonymyDao.checkSynonymyConflict(param);
			Map<String, Object> param2 = new HashMap<>();
			param2.put("list", wordList);
			if (StringUtils.equalsIgnoreCase(property, "o")) {
				param2.put("propertyFlag", "oa");
				param2.put("propertyFlag2", "o");
			} else {
				param2.put("propertyFlag", "o");
				param2.put("propertyFlag2", "oa");
			}
			param2.put("synonymyId", id);
			// 校验拆分的一个同义词拆分成几个同义词
			checkSynonymy2 = synonymyDao.checkSynonymyConflict2(param2);
		}
		List<Synonymy> rtn = new ArrayList<>();
		if (checkSynonymy != null) {
			if (checkSynonymy.size() > 1) {
				rtn.addAll(checkSynonymy);
				for (Synonymy value : checkSynonymy) {
					addIdList.add(value.getId() + "");
				}
			}
		}
		if (checkSynonymy2 != null) {
			if (checkSynonymy2.size() > 0) {
				for (Synonymy value : checkSynonymy2) {
					if (!addIdList.contains(value.getId() + "")) {
						rtn.add(value);
						addIdList.add(value.getId() + "");
					}
				}
			}
		}
		return rtn.size() > 0 ? rtn : null;
	}

	/**
	 * 编辑同义词，新增或修改
	 */
	public ReturnData edit(Integer type, String id, String property, String[] wordArray, User user, String std,
			String englishStd, boolean updateDiseaseFlag) {
		// 将wordArray中空的去除
		List<String> wordList = new ArrayList<>();
		std = changeStr(std).trim();
		englishStd = changeStr(englishStd).trim();
		// 小词t的量化
		List<String> quantization = new ArrayList<>();
		List<VocabElement> emptyQuantization = new ArrayList<>();
		for (String word : wordArray) {
			if (!word.isEmpty()) {
				word = changeStr(word).trim();
				if (!wordList.contains(word)) {
					wordList.add(word);
				} else {
					ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
					rc.setDesc("该同义词重复:" + word);
					return ReturnUtil.fail(rc);
				}
				// 小词t 判断同义词中量化是否一致,若该同义词没有量化则找寻同义词中的量化进行量化
				if ("t".equals(property)) {
					VocabElement value = vocabElementDao.retrieveObjectByVocabAndProp(word, "t");
					if (value != null) {
						if (StringUtils.isBlank(value.getQuantization())) {
							emptyQuantization.add(value);
						} else {
							if (!quantization.contains(value.getQuantization())) {
								quantization.add(value.getQuantization());
							}
						}
					}
				}
			}
		}
		// 说明添加的同义词的量化有不同
		if (quantization.size() > 1) {
			return ReturnUtil.fail(ReturnCode.T_PROPERTY_SYNONYMY_QUANTIZATION_NOT_EQUEL);
		}

		if (englishStd != null && !englishStd.isEmpty() && !wordList.contains(englishStd)) {
			wordList.add(0, englishStd);
		}
		if (std != null && !std.isEmpty() && !wordList.contains(std)) {
			wordList.add(0, std);
		}
		List<Synonymy> existSynonymy = new ArrayList<>();
		String errMsg2 = "";
		List<String> addIdList = new ArrayList<>();
		if (type.equals(Synonymy.TYPE_ELEMENT)) {
			// 如果属性为空则编辑不成功，返回提示信息
			if (property == null || property.isEmpty()) {
				ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
				rc.setDesc("属性不能为空");
				return ReturnUtil.fail(rc);
			}
			// 校验同义词冲突针对o,oa,si,s
			List<Synonymy> rtnList = checkSynonymyConflict(id, property, wordList, addIdList);
			if (rtnList != null) {
				errMsg2 = "存在o,oa,s,si同义词冲突";
				existSynonymy.addAll(rtnList);
			}
		} else {
			property = property == null ? "" : property;
		}
		// 拼凑words字段
		StringBuffer wordBf = new StringBuffer();
		wordBf.append("\t");
		int wordCount = 0;
		String errMsg = "";
		for (String word : wordList) {
			word = word.trim();
			if (!word.isEmpty()) {
				// 查询是否有历史相同词语
				List<Synonymy> existSynonymySub = synonymyDao.retrieveRepeatWord(id, word, property, type);
				if (existSynonymySub.size() > 0) {
					errMsg += word + "、";
					for (Synonymy value : existSynonymySub) {
						if (!addIdList.contains(value.getId() + "")) {
							existSynonymy.add(value);
						}
					}
				}
				wordBf.append(word);
				wordBf.append("\t");
				wordCount++;
			}
		}
		// 如果有重复的词语则编辑不成功，返回提示信息
		String err = "";
		if (!errMsg.isEmpty()) {
			errMsg = "系统中已存在以下词语的同义词：" + errMsg.substring(0, errMsg.length() - 1);
			err += errMsg;
		}
		if (!errMsg2.isEmpty()) {
			err += errMsg2;
		}
		if (StringUtils.isNotBlank(err)) {
			Map<String, Object> data = new HashMap<>();
			data.put("existList", getExistList(existSynonymy));
			data.put("errMsg", err);
			return ReturnUtil.fail(ReturnCode.SYNONYMY_EXISTS, data);
		}

		// 词语不足两个则不成功，返回提示信息
		if (wordCount < 2) {
			return ReturnUtil.fail(ReturnCode.SYNONYMY_LESS_THAN_TWO);
		}

		// TODO
		// 新的疾病维表上线后需要对疾病维表做校验：在同一组同义词中不能有两个有效疾病、如果有有效疾病必然是标准词、同义词中对应的性别年龄不能有冲突

		// 为同义词t 更新上量化
		for (VocabElement value : emptyQuantization) {
			if (quantization.size() == 1) {
				value.setQuantization(quantization.get(0));
				vocabElementDao.update(value);
			}
		}
		// 如果id存在则为修改，否则为新增
		Long synonymyId = 0l;
		if (id != null && !id.isEmpty()) {
			synonymyId = Long.parseLong(id);
			Synonymy synonymy = synonymyDao.retrieveObjectById(synonymyId);
			synonymy.setProperty(property);
			synonymy.setWords(wordBf.toString());
			synonymy.setChineseStd(std == null ? "" : std);
			synonymy.setEnglishStd(englishStd == null ? "" : englishStd);
			if (StringUtils.isNotBlank(synonymy.getChineseStd())) {
				synonymy.setStd(synonymy.getChineseStd());
			} else {
				synonymy.setStd(synonymy.getEnglishStd());
			}
			synonymy.setModifierId(user.getUserId());
			synonymy.setModifierName(user.getRealName());
			synonymyDao.update(synonymy);

			// 删除历史词语数据
			synonymyWordDao.deleteBySynonymyId(synonymyId);
		} else {
			Synonymy synonymy = new Synonymy();
			synonymy.setStd("");
			synonymy.setWords(wordBf.toString());
			synonymy.setChineseStd(std == null ? "" : std);
			synonymy.setEnglishStd(englishStd == null ? "" : englishStd);
			if (StringUtils.isNotBlank(synonymy.getChineseStd())) {
				synonymy.setStd(synonymy.getChineseStd());
			} else {
				synonymy.setStd(synonymy.getEnglishStd());
			}
			synonymy.setProperty(property);
			synonymy.setType(type);
			synonymy.setModifierId(user.getUserId());
			synonymy.setModifierName(user.getRealName());
			synonymyId = synonymyDao.insert(synonymy);
		}

		// 批量添加词语数据
		synonymyWordDao.batchInsert(synonymyId, wordList, user, type, property);

		// 校验标准词
		// String wrongStd = checkStd();
		// if(!wrongStd.isEmpty()) {
		// ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
		// rc.setDesc(wrongStd);
		//
		// return ReturnUtil.fail(rc);
		// }
		if ("di".equals(property) && updateDiseaseFlag) {
			icdDiseaseHospitalService.initHospitalDiseaseStdDisable();
		}
		return ReturnUtil.success();
	}

	private List<Map<String, Object>> getExistList(List<Synonymy> existSynonymy) {
		if (existSynonymy == null || existSynonymy.isEmpty()) {
			return null;
		}

		List<Map<String, Object>> returnMap = new ArrayList<>();
		List<Long> idArray = new ArrayList<>();
		for (Synonymy exist : existSynonymy) {
			if (!idArray.contains(exist.getId())) {
				Map<String, Object> map = new HashMap<>();
				map.put("id", exist.getId());
				map.put("property", exist.getProperty());
				map.put("std", exist.getStd());
				map.put("chineseStd", exist.getChineseStd());
				map.put("englishStd", exist.getEnglishStd());
				map.put("wordArray", BusinessUtil.getSynonymyArray(exist.getWords()));
				returnMap.add(map);
				idArray.add(exist.getId());
			}
		}
		return returnMap;
	}

	public ReturnData delete(String id) {
		// 删除标准词
		synonymyDao.delete(Long.parseLong(id));

		// 删除对应分词
		synonymyWordDao.deleteBySynonymyId(Long.parseLong(id));

		return ReturnUtil.success();
	}

	public ReturnData merge(String[] ids, User user) {
		if (ids.length < 2) {
			return ReturnUtil.fail(ReturnCode.MERGE_NUM_LESS_THAN_TWO);
		}

		String idsStr = getStrByArray(ids);

		List<Synonymy> synonymyList = synonymyDao.retrieveListByIds(idsStr);

		int type = 0;

		// 将合并同义词的所有词语合并且去重
		List<String> wordList = new ArrayList<String>();
		StringBuffer newWords = new StringBuffer();
		newWords.append("\t");
		String property = synonymyList.get(0).getProperty();
		String stdChinese = "";
		String stdEnglish = "";
		for (Synonymy synonymy : synonymyList) {
			if (!property.equals(synonymy.getProperty())) {
				return ReturnUtil.fail(ReturnCode.MERGE_PROPERTY_NOT_EQUALS);
			}
			if ("t".equals(synonymy.getProperty()) || "t".equals(property)) {
				return ReturnUtil.fail(ReturnCode.T_PROPERTY_NOT_MERGE);
			}
			String[] wordArray = synonymy.getWords().trim().split("\t");
			for (String word : wordArray) {
				if (!word.isEmpty() && !wordList.contains(word)) {
					newWords.append(word);
					newWords.append("\t");
					wordList.add(word);
				}
			}

			type = synonymy.getType();
			stdChinese = synonymy.getChineseStd();
			stdEnglish = synonymy.getEnglishStd();
		}

		// TODO
		// 新的疾病维表上线后需要对疾病维表做校验：在同一组同义词中不能有两个有效疾病、如果有有效疾病必然是标准词、同义词中对应的性别年龄不能有冲突

		// 历史的删除，新增一条合并后的数据
		Synonymy result = synonymyList.get(0);
		result.setType(type);
		result.setChineseStd(stdChinese);
		result.setEnglishStd(stdEnglish);
		result.setStd(stdChinese == null ? stdEnglish : stdChinese);
		result.setWords(newWords.toString());
		result.setModifierId(user.getUserId());
		result.setModifierName(user.getRealName());
		synonymyDao.insert(result);

		synonymyDao.deleteByIds(idsStr);

		// 批量添加词语数据
		synonymyWordDao.deleteWithoutSynonymy();
		synonymyWordDao.batchInsert(result.getId(), wordList, user, type, property);

		if (Synonymy.TYPE_ELEMENT.equals(type) && result.getStd().isEmpty()) {
			// 如果是小词同义词则初始化标准词
			synonymyDao.initStdById(result.getId());
			Synonymy syn = synonymyDao.retrieveObjectById(result.getId());
			if (syn != null) {
				String regEx = "[\u4E00-\u9FA5]";
				Pattern p = Pattern.compile(regEx);
				// 判断是中文标准词
				if (p.matcher(syn.getStd()).find()) {
					syn.setChineseStd(syn.getStd());
				} else {
					syn.setEnglishStd(syn.getStd());
				}
				synonymyDao.update(syn);
			}
		}
		if ("di".equals(property)) {
			icdDiseaseHospitalService.initHospitalDiseaseStdDisable();
		}

		return ReturnUtil.success();
	}

	private String getStrByArray(String[] ids) {
		StringBuffer idStr = new StringBuffer("(");
		for (int i = 0; i < ids.length; i++) {
			String id = ids[i];
			idStr.append(id);
			if (i == ids.length - 1) {
				idStr.append(")");
			} else {
				idStr.append(",");
			}
		}
		return idStr.toString();
	}

	public ReturnData editBatch(Integer type, List<Map<String, Object>> params, String ids, User user) {
		// 判断词语中是否有当前重复或系统已存在的数据
		StringBuffer errMsg = new StringBuffer();
		StringBuffer diErrMsg = new StringBuffer();
		StringBuffer currentErrMsg = new StringBuffer();
		StringBuffer synErrMsg = new StringBuffer();
		StringBuffer updateErrMsg = new StringBuffer();
		Map<String, String> idWords = new HashMap<>();

		Map<String, List<String>> currentWords = new HashMap<>();
		List<VocabElement> updateQuantizationList = new ArrayList<>();
		for (Map<String, Object> param : params) {
			String id = param.get("id").toString();
			String[] words = (String[]) param.get("words");
			String property = param.get("property") == null ? "" : param.get("property").toString();
			// 全部转成大写
			for (int i = 0; i < words.length; i++) {
				words[i] = changeStr(words[i]).trim();
			}

			// TODO
			// 新的疾病维表上线后需要对疾病维表做校验：在同一组同义词中不能有两个有效疾病、如果有有效疾病必然是标准词、同义词中对应的性别年龄不能有冲突

			// 校验同义词冲突针对o,oa,si,s
			List<Synonymy> rtn = checkSynonymyConflict(id, property, CollectionUtil.getListByArray(words),
					new ArrayList<String>());
			if (rtn != null) {
				if (synErrMsg.length() == 0) {
					synErrMsg = new StringBuffer("以下同义词存在同义词冲突：");
				}
				synErrMsg.append(CollectionUtil.getListByArray(words).toString());
				synErrMsg.append("；");
			}

			StringBuffer wordsSb = new StringBuffer();
			// 小词t的量化
			List<String> quantization = new ArrayList<>();
			List<VocabElement> emptyQuantization = new ArrayList<>();
			for (String word : words) {
				word = word.trim();
				if (word.isEmpty()) {
					continue;
				}
				// 小词t 判断同义词中量化是否一致,若该同义词没有量化则找寻同义词中的量化进行量化
				if ("t".equals(property)) {
					VocabElement value = vocabElementDao.retrieveObjectByVocabAndProp(word, "t");
					if (value != null) {
						if (StringUtils.isBlank(value.getQuantization())) {
							emptyQuantization.add(value);
						} else {
							if (!quantization.contains(value.getQuantization())) {
								quantization.add(value.getQuantization());
							}
						}
					}
				}
				// 当前要提交数据中是否有重复的词语
				if (currentWords.containsKey(property)) {
					if (currentWords.get(property).contains(word)) {
						if (currentErrMsg.length() == 0) {
							currentErrMsg = new StringBuffer("当前数据有重复词语：");
						}
						currentErrMsg.append(word);
						currentErrMsg.append("、");
					} else {
						currentWords.get(property).add(word);
					}
				} else {
					List<String> wordList = new ArrayList<>();
					wordList.add(word);
					currentWords.put(property, wordList);
				}

				List<Synonymy> existSynonymySub = synonymyDao.retrieveRepeatWord(ids, word, property, type);
				if (existSynonymySub.size() > 0) {
					if (errMsg.length() == 0) {
						errMsg = new StringBuffer("系统中已存在以下词语的同义词：");
					}
					errMsg.append(word);
					errMsg.append("、");
				}
				wordsSb.append("\t");
				wordsSb.append(word);
			}
			idWords.put(id, wordsSb.append("\t").toString());
			if (quantization.size() > 1) {
				if (updateErrMsg.length() == 0) {
					updateErrMsg = new StringBuffer("当前添加的同义词存在量化不同的情况:");
				}
				updateErrMsg.append(CollectionUtil.getListByArray(words).toString());
				updateErrMsg.append("、");
			}
			// 添加需要更新的t 的量化
			// 为同义词t 更新上量化
			for (VocabElement value : emptyQuantization) {
				if (quantization.size() == 1) {
					value.setQuantization(quantization.get(0));
					updateQuantizationList.add(value);
				}
			}
		}

		// 如果有存在的数据则返回错误信息
		if (errMsg.length() > 0 || diErrMsg.length() > 0 || currentErrMsg.length() > 0 || synErrMsg.length() > 0
				|| updateErrMsg.length() > 0) {
			Map<String, Object> map = new HashMap<>();
			map.put("errMsg", errMsg.toString() + "\n" + diErrMsg.toString() + "\n" + currentErrMsg.toString() + "\n"
					+ synErrMsg.toString() + "\n" + updateErrMsg.toString());
			return ReturnUtil.fail(ReturnCode.SYNONYMY_EXISTS, map);
		}
		// 根据同义词更新小词t上的量化
		for (VocabElement value : updateQuantizationList) {
			vocabElementDao.update(value);
		}
		List<String> propertyList = new ArrayList<>();
		// 对数据进行保存
		for (Map<String, Object> param : params) {
			String id = param.get("id").toString();
			String property = param.get("property") == null ? "" : param.get("property").toString();
			String std = param.get("std") == null ? "" : changeStr(param.get("std").toString()).trim();
			String words = idWords.get(id);
			String englishStd = param.get("englishStd") == null ? ""
					: changeStr(param.get("englishStd").toString()).trim();
			propertyList.add(property);
			List<String> wordList = Arrays.asList(words.substring(1, words.length()).split("\t"));

			Long synonymyId = 0l;
			if (id != null && !id.isEmpty()) {
				synonymyId = Long.parseLong(id);
				Synonymy synonymy = synonymyDao.retrieveObjectById(synonymyId);
				synonymy.setProperty(property);
				synonymy.setChineseStd(std == null ? "" : std);
				synonymy.setEnglishStd(englishStd);
				if (StringUtils.isNotBlank(synonymy.getChineseStd())) {
					synonymy.setStd(synonymy.getChineseStd());
				} else {
					synonymy.setStd(synonymy.getEnglishStd());
				}
				synonymy.setWords(words);
				synonymy.setModifierId(user.getUserId());
				synonymy.setModifierName(user.getRealName());
				synonymyDao.update(synonymy);

				// 删除历史词语数据
				synonymyWordDao.deleteBySynonymyId(synonymyId);
			} else {
				Synonymy synonymy = new Synonymy();
				synonymy.setType(type);
				synonymy.setChineseStd(std == null ? "" : std);
				synonymy.setWords(words);
				synonymy.setEnglishStd(englishStd);
				if (StringUtils.isNotBlank(synonymy.getChineseStd())) {
					synonymy.setStd(synonymy.getChineseStd());
				} else {
					synonymy.setStd(synonymy.getEnglishStd());
				}
				synonymy.setProperty(property);
				synonymy.setModifierId(user.getUserId());
				synonymy.setModifierName(user.getRealName());
				synonymyId = synonymyDao.insert(synonymy);
			}

			// 批量添加词语数据
			synonymyWordDao.batchInsert(synonymyId, wordList, user, type, property);
		}
		if (propertyList.contains("di")) {
			icdDiseaseHospitalService.initHospitalDiseaseStdDisable();
		}
		return ReturnUtil.success();
	}

	@SuppressWarnings("resource")
	public ReturnData synonymImport(Integer type, MultipartFile mFile, User user, String property) throws Exception {
		if (type.equals(Synonymy.TYPE_ELEMENT)) {
			// 校验文件名
			if (!VocabConstant.elementProperty.contains(property)) {
				LOGGER.info("synonymImport failed,property={}", property);
				return ReturnUtil.fail(ReturnCode.EXCEPTION);
			}
		}

		// 获取文件流，解析文件
		List<String> synonymList = new ArrayList<>();
		InputStream inputStream = mFile.getInputStream();

		Workbook workbook = new XSSFWorkbook(inputStream);
		Sheet sheet = workbook.getSheetAt(0);

		StringBuffer errorMsg = new StringBuffer(); // 记录下重复的词语
		StringBuffer diErrMsg = new StringBuffer();
		StringBuffer conflictErrMsg = new StringBuffer();
		StringBuffer stdEngStdErrMsg = new StringBuffer();
		StringBuffer stdNonExtMsg = new StringBuffer();
		StringBuffer tQuantizationErrMsg = new StringBuffer();
		StringBuffer errDi = new StringBuffer();

		List<String> wordsList = new ArrayList<>(); // 记录下所有的词语，用来做重复判断
		List<String> diWordsList = new ArrayList<>(); // 记录下di所有的词语做有效词语校验
		Map<String, String> checkSynonymyConflictMap = new HashMap<>();
		List<SynonymyWord> checkList = new ArrayList<>();
		List<Synonymy> checkList2 = new ArrayList<>();
		List<String> checkSynonymyConflictList = new ArrayList<>();
		if (StringUtils.equalsIgnoreCase("o", property)) {
			Map<String, Object> param = new HashMap<>();
			param.put("type", "1");
			param.put("property", "oa");
			checkList = synonymyWordDao.retrieveList(param);
			checkList2 = synonymyDao.retrieveList(param);
		} else if (StringUtils.equalsIgnoreCase("oa", property)) {
			Map<String, Object> param = new HashMap<>();
			param.put("type", "1");
			param.put("property", "o");
			checkList = synonymyWordDao.retrieveList(param);
			checkList2 = synonymyDao.retrieveList(param);

		} else if (StringUtils.equalsIgnoreCase("s", property)) {
			Map<String, Object> param = new HashMap<>();
			param.put("type", "1");
			param.put("property", "si");
			checkList = synonymyWordDao.retrieveList(param);
			checkList2 = synonymyDao.retrieveList(param);

		} else if (StringUtils.equalsIgnoreCase("si", property)) {
			Map<String, Object> param = new HashMap<>();
			param.put("type", "1");
			param.put("property", "s");
			checkList = synonymyWordDao.retrieveList(param);
			checkList2 = synonymyDao.retrieveList(param);
		}
		if (checkList != null && checkList.size() > 0) {
			for (SynonymyWord syw : checkList) {
				checkSynonymyConflictMap.put(syw.getWord(), syw.getSynonymyId() + "");
			}
		}
		if (checkList2 != null && checkList2.size() > 0) {
			for (Synonymy sy : checkList2) {
				checkSynonymyConflictList.add(sy.getWords());
			}
		}
		Map<String, String> checkConflictMap2 = new HashMap<>();
		List<Synonymy> synList = new ArrayList<>();
		List<VocabElement> updateTQuantizationList = new ArrayList<>();

		int j = 1;
		int k = 1;
		boolean spaceFlag = false;
		for (Row row : sheet) {
			spaceFlag = false;
			StringBuffer synonymy = new StringBuffer();
			synonymy.append("\t");
			Map<String, String> checkSynonymyMap = new HashMap<>();
			Synonymy s = new Synonymy();
			String englishStd = "";
			String std = "";
			int num = row.getLastCellNum();
			// 小词t的量化
			List<String> quantization = new ArrayList<>();
			List<VocabElement> emptyQuantization = new ArrayList<>();
			for (int i = 0; i < num; i++) {
				Cell cell = row.getCell(i);
				if (cell != null) {
					cell.setCellType(Cell.CELL_TYPE_STRING);
					String word = changeStr(cell.getStringCellValue().trim());
					if (StringUtils.isBlank(word) && (i > 1)) {
						spaceFlag = true;
					}
					// 记录每一行 用于校验冲突
					if (checkList != null && checkList.size() > 0) {
						checkConflictMap2.put(word, j + "");
					}
					// 校验是否冲突
					// 小词规则
					if (type.equals(Synonymy.TYPE_ELEMENT)) {

						// 第一行是中文标准词
						if (i == 0) {
							// 由于cell从不为空的列开始读,需要判断标准词是否为空
							if (StringUtils.isNotBlank(word) && row.getCell(0) != null) {
								std = word;
							} else if (StringUtils.isNotBlank(word)) {
								if (wordsList.contains(word)) {
									if (errorMsg.length() == 0) {
										errorMsg = new StringBuffer("系统中已存在以下词语的同义词：");
									}
									errorMsg.append(word);
									errorMsg.append("，");
								}
								wordsList.add(word);
								diWordsList.add(word);
								synonymy.append(word);
								synonymy.append("\t");
							}
						}
						if (i == 1) {
							if (StringUtils.isNotBlank(word)) {
								englishStd = word;
							}
						}
						if (!word.isEmpty()) {
							if (spaceFlag) {
								ReturnCode rc = ReturnCode.DYNAMIC_DESC_EXCEPTION;
								rc.setDesc("第" + k + "行存在空格");
								return ReturnUtil.fail(rc);
							}
							// 中文标准词和英文标准词不记入校验
							if (i != 0 && i != 1) {
								if (wordsList.contains(word)) {
									if (errorMsg.length() == 0) {
										errorMsg = new StringBuffer("系统中已存在以下词语的同义词：");
									}
									errorMsg.append(word);
									errorMsg.append("，");
								}
								// 小词t 判断同义词中量化是否一致,若该同义词没有量化则找寻同义词中的量化进行量化
								if ("t".equals(property)) {
									VocabElement value = vocabElementDao.retrieveObjectByVocabAndProp(word, "t");
									if (value != null) {
										if (StringUtils.isBlank(value.getQuantization())) {
											emptyQuantization.add(value);
										} else {
											if (!quantization.contains(value.getQuantization())) {
												quantization.add(value.getQuantization());
											}
										}
									}
								}
								wordsList.add(word);
								diWordsList.add(word);
								synonymy.append(word);
								synonymy.append("\t");
							}

							// 校验同义词冲突
							if (checkSynonymyConflictMap != null && checkSynonymyConflictMap.size() > 0) {
								String synonymyId = checkSynonymyConflictMap.get(word);
								if (StringUtils.isNotBlank(synonymyId)) {
									checkSynonymyMap.put(synonymyId, "1");
								}
							}
						}
					} else {
						// 大白话同义词
						// 第一行是中文标准词
						if (i == 0) {
							// 如果第一行为空没有标准词 cell从第一列不为空的字段开始取
							if (StringUtils.isNotBlank(word) && row.getCell(0) != null) {
								std = word;
							} else if (StringUtils.isNotBlank(word)) {
								if (wordsList.contains(word)) {
									if (errorMsg.length() == 0) {
										errorMsg = new StringBuffer("系统中已存在以下词语的同义词：");
									}
									errorMsg.append(word);
									errorMsg.append("，");
								}
								wordsList.add(word);
								synonymy.append(word);
								synonymy.append("\t");
							}
						}
						if (!word.isEmpty() && i != 0) {
							if (wordsList.contains(word)) {
								if (errorMsg.length() == 0) {
									errorMsg = new StringBuffer("系统中已存在以下词语的同义词：");
								}
								errorMsg.append(word);
								errorMsg.append("，");
							}
							wordsList.add(word);
							synonymy.append(word);
							synonymy.append("\t");
						}

					}
				}
			}

			if (StringUtils.isNotBlank(synonymy.toString())) {
				synonymList.add(synonymy.toString());
				s.setEnglishStd(englishStd);
				s.setWords(synonymy.toString());
				s.setChineseStd(std);

				if (StringUtils.isNotBlank(s.getChineseStd())) {
					s.setStd(s.getChineseStd());
				} else if (StringUtils.isNotBlank(s.getEnglishStd())) {
					s.setStd(s.getEnglishStd());
				}
				synList.add(s);
				// 校验标准词是否在同义词列表中
				if (StringUtils.isNotBlank(std) && !synonymy.toString().contains(std)) {
					if (stdNonExtMsg.length() == 0) {
						stdNonExtMsg = new StringBuffer("该条标准词不在同义词列表：");
					}
					stdNonExtMsg.append(synonymy.toString());
					stdNonExtMsg.append("；");
				}
				if (StringUtils.isNotBlank(englishStd) && !synonymy.toString().contains(englishStd)) {
					if (stdNonExtMsg.length() == 0) {
						stdNonExtMsg = new StringBuffer("该条标准词不在同义词列表：");
					}
					stdNonExtMsg.append(synonymy.toString());
					stdNonExtMsg.append("；");
				}
				// end
				if (StringUtils.isBlank(englishStd) && StringUtils.isBlank(std) && type.equals(Synonymy.TYPE_ELEMENT)) {
					if (stdEngStdErrMsg.length() == 0) {
						stdEngStdErrMsg = new StringBuffer("该条同义词无标准词：");
					}
					stdEngStdErrMsg.append(synonymy.toString());
					stdEngStdErrMsg.append("；");
				}
				if (checkSynonymyMap != null && checkSynonymyMap.size() > 1) {
					if (conflictErrMsg.length() == 0) {
						conflictErrMsg = new StringBuffer("该条同义词存在冲突：");
					}
					conflictErrMsg.append(synonymy.toString());
					conflictErrMsg.append("；");
				}

				// TODO
				// 新的疾病维表上线后需要对疾病维表做校验：在同一组同义词中不能有两个有效疾病、如果有有效疾病必然是标准词、同义词中对应的性别年龄不能有冲突

				diWordsList = new ArrayList<>();
				// 说明添加的同义词的量化有不同
				if (quantization.size() > 1) {
					if (tQuantizationErrMsg.length() == 0) {
						tQuantizationErrMsg = new StringBuffer("该条同义词t的量化结果不同:");
					}
					tQuantizationErrMsg.append(synonymy.toString());
					tQuantizationErrMsg.append("；");
				}
			}
			for (VocabElement value : emptyQuantization) {
				if (quantization.size() == 1) {
					value.setQuantization(quantization.get(0));
					updateTQuantizationList.add(value);
				}
			}
			j++;
			k++;
		}

		// 校验o,oa,s,si冲突
		for (String words : checkSynonymyConflictList) {
			String[] wordArr = words.split("\t");
			String temp = "";
			for (String word : wordArr) {
				if (StringUtils.isNotBlank(word) && checkConflictMap2.get(word) != null) {
					if (StringUtils.isBlank(temp)) {
						temp = checkConflictMap2.get(word);
					} else {
						if (!StringUtils.equals(temp, checkConflictMap2.get(word))) {
							if (conflictErrMsg.length() == 0) {
								conflictErrMsg = new StringBuffer("该条同义词存在冲突：");
							}
							conflictErrMsg.append(word);
							conflictErrMsg.append("；");
							continue;
						}
					}
				}
			}
		}
		if (errorMsg.length() > 0 || diErrMsg.length() > 0 || conflictErrMsg.length() > 0
				|| stdEngStdErrMsg.length() > 0 || stdNonExtMsg.length() > 0 || tQuantizationErrMsg.length() > 0
				|| errDi.length() > 0) {
			// 表示有重复的词语，报错
			Map<String, Object> map = new HashMap<>();
			map.put("errorMsg",
					errorMsg.toString() + "\n" + diErrMsg.toString() + "\n" + conflictErrMsg.toString() + "\n"
							+ stdEngStdErrMsg.toString() + "\n" + stdNonExtMsg.toString() + "\n"
							+ tQuantizationErrMsg.toString() + "\n" + errDi.toString());

			LOGGER.info(errorMsg.toString() + "\n" + diErrMsg.toString() + "\n" + conflictErrMsg.toString() + "\n"
					+ stdNonExtMsg.toString() + "\n" + tQuantizationErrMsg.toString() + "\n" + errDi.toString());
			workbook.close();
			inputStream.close();
			return ReturnUtil.fail(ReturnCode.SYNONYMY_EXISTS, map);
		}
		// 更新同义词中 的量化到小词表
		for (VocabElement value : updateTQuantizationList) {
			vocabElementDao.update(value);
		}
		// 删除数据库对应同义词及分词数据
		Map<String, Object> param = new HashMap<>();
		param.put("type", type);
		param.put("property", VocabConstant.elementProperty.contains(property) ? property : "");
		synonymyWordDao.deleteByMap(param);
		synonymyDao.deleteByMap(param);
		LOGGER.info("synonymImport delete success,property={}, type={}", new Object[] { property, type });

		// 批量添加数据
		synonymyDao.batchInsert(type, synList, VocabConstant.elementProperty.contains(property) ? property : "",
				user.getUserId(), user.getRealName());
		synonymyWordDao.batchInsertBySynonymy(type, VocabConstant.elementProperty.contains(property) ? property : "");
		LOGGER.info("synonymImport insert success,property={}", property);

		workbook.close();
		inputStream.close();
		if ("di".equals(property)) {
			icdDiseaseHospitalService.initHospitalDiseaseStdDisable();
		}
		return ReturnUtil.success();
	}
	// 转大写。除了希腊字母
    public static String changeStr(String str){
    	if(str == null) {
    		return "";
    	}
        str.toUpperCase();  
        char[] ch = str.toCharArray();  
        StringBuffer sb = new StringBuffer();  
        int a = 'A'-'a';   //获得大小写之间差值  
        for(int i = 0; i < ch.length; i++){  
            if('a' <= ch[i] && ch[i] <= 'z'){  
                ch[i] = (char)(ch[i]+a);  
            }  
            sb.append(ch[i]);  
        }  
          
        return sb.toString();  
    } 
	/**
	 * 同义词导出。由于各种同义词有各自的需求，所以按类型写不同的导出方法。
	 * 小词导出主要根据正确小词为标准，导出列为：是否校验、正确小词、标准词、其他同义词；由于小词是动态的，在导出时先进行标准词的校正
	 * 
	 * @param type
	 * @param property
	 * @param resp
	 * @throws Exception
	 */
	public void synonymExport(Integer type, String property, HttpServletResponse resp, String no) throws Exception {

		OutputStream os = resp.getOutputStream();

		if (no != null && "2".equals(no)) {
			// 小词同义词导出
			elementSynonymyExport(property, resp, os);
		} else {
			// 同义词导出
			synonymyExport(type, property, resp, os);
		}

		os.close();
	}

	private void synonymyExport(Integer type, String property, HttpServletResponse resp, OutputStream os)
			throws Exception {
		// 设置respons的头信息
		String fileName = "element";
		if (type.equals(Synonymy.TYPE_ELEMENT)) {
			fileName = property;
		} else if (type.equals(Synonymy.TYPE_SLANG)) {
			fileName = "slang";
		}
		RespHeaderUtil.setXlsxResp(resp, fileName);

		XSSFWorkbook workbook = new XSSFWorkbook(); // 创建文档
		XSSFCellStyle style = ExcelUtil.getFontColorStyle(workbook, HSSFColor.RED.index);

		// 根据property和type获取同义词列表
		Map<String, Object> param = new HashMap<>();
		param.put("property", VocabConstant.elementProperty.contains(property) ? property : "");
		param.put("type", type);
		List<Synonymy> synonymList = synonymyDao.retrieveList(param);

		// 获取对应所有的分词列表
		List<SynonymyWord> words = synonymyWordDao.retrieveList(param);
		Map<Long, List<SynonymyWord>> wordMap = new HashMap<>();
		Long synonymyId = 0L;
		List<SynonymyWord> tempList = new ArrayList<>();
		for (SynonymyWord word : words) {
			synonymyId = word.getSynonymyId();
			if ((tempList = wordMap.get(synonymyId)) == null) {
				tempList = new ArrayList<>();
				tempList.add(word);
				wordMap.put(synonymyId, tempList);
			} else {
				tempList.add(word);
			}
		}
		XSSFSheet sheet = workbook.createSheet(fileName); // 创建Sheet
		// 如果是小词同义词则需要区分出（正确小词+错别字）的词语
		if (type.equals(Synonymy.TYPE_ELEMENT)) {
			List<String> elementList = synonymyWordDao.retrieveRightOrReplaceVocabElementList(property);
			// 循环写入数据
			for (int i = 0; i < synonymList.size(); i++) {
				Synonymy synonymy = synonymList.get(i);

				XSSFRow row = sheet.createRow(i);
				// 如果是小词同义词中有标准词的，则需要将标准词放在每行的第一格；如果标准词不存在则空,英文标准词同样操作
				Cell cell = row.createCell(0);
				cell.setCellValue(StringUtils.isNotBlank(synonymy.getChineseStd()) ? synonymy.getChineseStd() : "");
				if (!elementList.contains(synonymy.getChineseStd())) {
					cell.setCellStyle(style);
				}
				Cell cell1 = row.createCell(1);
				cell1.setCellValue(StringUtils.isNotBlank(synonymy.getEnglishStd()) ? synonymy.getEnglishStd() : "");
				if (!elementList.contains(synonymy.getEnglishStd())) {
					cell1.setCellStyle(style);
				}
				setCell(2, wordMap.get(synonymy.getId()), "", workbook, elementList, row, style, "");
			}
		} else {
			// 循环写入数据
			for (int i = 0; i < synonymList.size(); i++) {
				Synonymy synonymy = synonymList.get(i);
				XSSFRow row = sheet.createRow(i);
				Cell cell = row.createCell(0);
				cell.setCellValue(StringUtils.isNotBlank(synonymy.getChineseStd()) ? synonymy.getChineseStd() : "");

				setCell(1, wordMap.get(synonymy.getId()), "", workbook, null, row, style, "");
			}
		}

		workbook.write(os);

		workbook.close();

		LOGGER.info("[synonymExport]End!Params:type={},property={}", new Object[] { type, property });
	}

	private void setCell(int cellIndex, List<SynonymyWord> synonymyWordList, String std, Workbook workbook,
			List<String> elementList, XSSFRow row, XSSFCellStyle style, String englishStd) {
		XSSFCell cell;
		if (synonymyWordList != null) {
			// 第一遍循环把（正确小词+错别字）插入，如果小词列表为空则表示是大白话，第一遍就插入完整
			for (SynonymyWord synonymyWord : synonymyWordList) {
				if (elementList == null || elementList.contains(synonymyWord.getWord())
						&& !synonymyWord.getWord().equals(std) && !synonymyWord.getWord().equals(englishStd)) {
					cell = row.createCell(cellIndex);
					cell.setCellValue(synonymyWord.getWord());
					cellIndex++;
				}
			}
			// 第二遍循环把其他词语插入，设置为红色的字
			for (SynonymyWord synonymyWord : synonymyWordList) {
				if (elementList != null && !elementList.contains(synonymyWord.getWord())
						&& !synonymyWord.getWord().equals(std) && !synonymyWord.getWord().equals(englishStd)) {
					cell = row.createCell(cellIndex);
					cell.setCellStyle(style);
					cell.setCellValue(synonymyWord.getWord());
					cellIndex++;
				}
			}
		}
	}

	private void elementSynonymyExport(String property, HttpServletResponse resp, OutputStream os) throws Exception {

		// 设置respons的头信息
		RespHeaderUtil.setXlsxResp(resp, "小词" + property);

		Workbook workbook = new XSSFWorkbook(); // 创建文档

		// 根据property和type获取同义词列表
		Map<String, Object> param = new HashMap<>();
		param.put("property", VocabConstant.elementProperty.contains(property) ? property : "");
		param.put("type", Synonymy.TYPE_ELEMENT);
		List<Synonymy> synonymList = synonymyDao.retrieveList(param);

		// 获取正确小词列表
		Map<String, Object> param1 = new HashMap<>();
		param1.put("property", VocabConstant.elementProperty.contains(property) ? property : "");
		param1.put("flag", BaseContants.FLAG_RIGHT);
		param1.put("orderStr", "synonymy_flag desc");
		List<VocabElement> elementList = vocabElementDao.retrieveList(param1);
		Sheet sheet = workbook.createSheet(property); // 创建Sheet
		// 循环写入数据
		for (int i = 0; i < elementList.size(); i++) {
			// 获取该小词对应的同义词
			VocabElement element = elementList.get(i);
			Synonymy synonymy = getSynonymyByElement(synonymList, element);

			Row row = sheet.createRow(i);
			setCell(row, 0, BaseContants.FLAG_YES.equals(element.getSynonymyFlag()) ? "是" : "否");
			setCell(row, 1, element.getVocabulary());
			if (synonymy != null) {
				setCell(row, 2, synonymy.getChineseStd());

				String[] words = synonymy.getWords().trim().split("\t");
				int k = 3;
				for (int j = 0; j < words.length; j++) {
					if (!words[j].equals(synonymy.getChineseStd())) {
						setCell(row, k, words[j]);
						k++;
					}
				}
			}
		}

		workbook.write(os);

		workbook.close();

		// 将当前正确的小词都设置为同义词已校验
		vocabElementDao.checkSynonymyFlag(property);

		LOGGER.info("Element synonymy export end!property = " + property);
	}

	private void setCell(Row row, int i, String string) {
		Cell cell = row.createCell(i);
		cell.setCellValue(string);
	}

	private Synonymy getSynonymyByElement(List<Synonymy> synonymList, VocabElement element) {
		for (Synonymy synonymy : synonymList) {
			if (synonymy.getWords().indexOf("\t" + element.getVocabulary() + "\t") > -1
					&& synonymy.getProperty().equals(element.getProperty())) {
				return synonymy;
			}
		}
		return null;
	}

	public ReturnData changeStd(String id, String word, String property, User user) {
		// TODO
		// 新的疾病维表上线后需要对疾病维表做校验：如果有有效疾病必然是标准词

		// 用于保留原来的一级
		Synonymy syn = synonymyDao.retrieveObjectById(Long.parseLong(id));
		synonymyDao.changeStd(Long.parseLong(id), word);
		synonymyDao.changeChineseStd(Long.parseLong(id), word);

		if ("di".equals(property)) {
			// 根据原来的疾病名查询出原来的一级,更新到现在的疾病名上
			List<Map<String, Object>> categoryId = icdDiseaseHospitalDao.getStdId(syn.getStd());
			Long category = 0L;
			if (categoryId != null && categoryId.size() > 0) {
				category = (Long) categoryId.get(0).get("category_id");
			}
			String disable = "";
			if (categoryId != null && categoryId.size() > 0) {
				disable = (String) categoryId.get(0).get("disable");
			}
			// 判断新的标准词是否存在在新疾病维表中
			List<Map<String, Object>> ids = icdDiseaseHospitalDao.getStdId(word);
			String diseaseId = "";
			for (Map<String, Object> temp : ids) {
				diseaseId = temp.get("id") + "";
			}
			if (StringUtils.isNotBlank(diseaseId)) {
				icdDiseaseHospitalDao.initHospitalDisease(diseaseId, id);
				icdDiseaseHospitalDao.updateStdDisableCategory(diseaseId, disable, user.getUserId(), category);
				icdDiseaseHospitalDao.initCategory(id, word);
				icdDiseaseHospitalDao.initCategory();
			} else {
				long newId = icdDiseaseHospitalDao.insertStd(word, user.getUserId());
				icdDiseaseHospitalDao.initHospitalDisease(newId + "", id);
				icdDiseaseHospitalDao.updateStdDisableCategory(newId + "", disable, user.getUserId(), category);
				icdDiseaseHospitalDao.initCategory(id, word);
				icdDiseaseHospitalDao.initCategory();
			}
		}
		return ReturnUtil.success();
	}

	public ReturnData changeEnglishStd(String id, String word, String property, User user) {
		// TODO
		// 新的疾病维表上线后需要对疾病维表做校验：如果有有效疾病必然是标准词

		// 如果没有中文标准词 用英文标准词更新std字段
		Synonymy syn = synonymyDao.retrieveObjectById(Long.parseLong(id));

		synonymyDao.changeEnglishStd(Long.parseLong(id), word);
		if (syn != null
				&& (StringUtils.isBlank(syn.getStd()) || !StringUtils.equals(syn.getStd(), syn.getChineseStd()))) {
			synonymyDao.changeStd(Long.parseLong(id), word);
		}
		if ("di".equals(property)) {
			// 根据原来的疾病名查询出原来的一级,更新到现在的疾病名上
			List<Map<String, Object>> categoryId = icdDiseaseHospitalDao.getStdId(syn.getStd());
			Long category = 0L;
			if (categoryId != null && categoryId.size() > 0) {
				category = (Long) categoryId.get(0).get("category_id");
			}
			String disable = "";
			if (categoryId != null && categoryId.size() > 0) {
				disable = (String) categoryId.get(0).get("disable");
			}
			// 判断新的标准词是否存在在新疾病维表中
			List<Map<String, Object>> ids = icdDiseaseHospitalDao.getStdId(word);
			String diseaseId = "";
			for (Map<String, Object> temp : ids) {
				diseaseId = temp.get("id") + "";
			}
			if (StringUtils.isNotBlank(diseaseId)) {
				icdDiseaseHospitalDao.initHospitalDisease(diseaseId, id);
				icdDiseaseHospitalDao.updateStdDisableCategory(diseaseId, disable, user.getUserId(), category);
				icdDiseaseHospitalDao.initCategory(id, word);
				icdDiseaseHospitalDao.initCategory();
			} else {
				long newId = icdDiseaseHospitalDao.insertStd(word, user.getUserId());
				icdDiseaseHospitalDao.initHospitalDisease(newId + "", id);
				icdDiseaseHospitalDao.updateStdDisableCategory(newId + "", disable, user.getUserId(), category);
				icdDiseaseHospitalDao.initCategory(id, word);
				icdDiseaseHospitalDao.initCategory();
			}
		}
		return ReturnUtil.success();
	}

	public List<String> getWordListByWord(String word, int type, String property) {
		return synonymyWordDao.retrieveWordListByWord(word, type, property);
	}

	public ReturnCode insertWordByTypeAndProperty(Integer type, String property, List<String> words, User user,
			String std) {
		// 根据一批词语查找现有的同义词
		List<Synonymy> synonymyList = synonymyDao.retrieveListByWords(type, property, words);
		if (synonymyList.size() > 1) {
			// 如果找到多条同义词数据，则返回提示信息
			return ReturnCode.SYNONYMY_WORDS_NOT_IN_SAME_DATA;
		} else if (synonymyList.size() == 0) {
			// 如果找不到现有的同义词数据，则新增一条
			return createSynonymy(type, property, words, user, std);
		} else {
			// 如果能找到一条同义词数据，则直接更改这条数据
			return insertWordIntoSynonymy(words, synonymyList.get(0), user, std);
		}
	}

	private ReturnCode insertWordIntoSynonymy(List<String> words, Synonymy synonymy, User user, String std) {
		boolean updateFlag = false; // 修改标志，在出现原同义词中不存在的词语时才更新
		String wordStr = synonymy.getWords();
		List<String> existWords = new ArrayList<>();
		for (String temp : wordStr.split("\t")) {
			if (!temp.isEmpty()) {
				existWords.add(temp);
			}
		}
		if (!existWords.containsAll(words)) {
			updateFlag = true;
			for (String word : words) {
				if (!existWords.contains(word)) {
					existWords.add(word);
				}
			}
		}
		if (updateFlag) {
			synonymy.setWords(getWordStrByList(existWords));
			synonymy.setModifierId(user.getUserId());
			synonymy.setModifierName(user.getRealName());
			if (std != null && !std.isEmpty()) {
				synonymy.setStd(std);
			}

			synonymyDao.update(synonymy);

			// 批量添加词语数据
			synonymyWordDao.deleteBySynonymyId(synonymy.getId());
			synonymyWordDao.batchInsert(synonymy.getId(), existWords, user, synonymy.getType(), synonymy.getProperty());
		}

		return ReturnCode.SUCCESS;
	}

	private ReturnCode createSynonymy(Integer type, String property, List<String> words, User user, String std) {

		// TODO
		// 新的疾病维表上线后需要对疾病维表做校验：在同一组同义词中不能有两个有效疾病、如果有有效疾病必然是标准词、同义词中对应的性别年龄不能有冲突

		Synonymy synonymy = new Synonymy();
		synonymy.setModifierId(user.getUserId());
		synonymy.setModifierName(user.getRealName());
		synonymy.setType(type);
		synonymy.setProperty(property);
		synonymy.setWords(getWordStrByList(words));
		String stdValue = getStdByWords(words, property, std);
		synonymy.setStd(stdValue);
		String reg = "^[u0391-uFFE5/!@#$%^&*()_+-=,./;\\<>?:{}|`~]*$";
		if (stdValue.matches(reg)) {
			synonymy.setEnglishStd(stdValue);
			synonymy.setChineseStd("");
		} else {
			synonymy.setEnglishStd("");
			synonymy.setChineseStd(getStdByWords(words, property, std));
		}
		long id = synonymyDao.insert(synonymy);
		// 批量添加词语数据
		synonymyWordDao.batchInsert(id, words, user, synonymy.getType(), property);

		return ReturnCode.SUCCESS;
	}

	@Autowired
	private VocabElementService vocabElementService;

	private String getStdByWords(List<String> words, String property, String std) {
		// 如果是di则查找是否有有效疾病名，有则设置为标准词
		if (VocabConstant.ELEMENT_DISEASE.equals(property)) {
			List<IcdDisease> diseaseList = icdDiseaseDao.retrieveValidListByNameArray(words);
			if (diseaseList.size() == 1) {
				return diseaseList.get(0).getName();
			} else {
				return "";
			}
		}

		// 其他小词按频数排序返回频数最大的词
		if (std == null || std.isEmpty()) {
			return vocabElementService.retrieveTheLargestCntWordByWords(words, property);
		} else {
			return std;
		}
	}

	private String getWordStrByList(List<String> words) {
		StringBuffer wordBf = new StringBuffer();
		wordBf.append("\t");
		for (String word : words) {
			wordBf.append(word);
			wordBf.append("\t");
		}
		return wordBf.toString();
	}

	/**
	 * 疾病di同义词标准词统一成罗马字符
	 */
	public void initDiSynonymyToRoman() {
		// 查询所有的di同义词
		Map<String, Object> param = new HashMap<>();
		param.put("property", "di");
		param.put("type", 1);
		List<Synonymy> syList = synonymyDao.retrieveList(param);
		// 查询所有的同义词
		List<SynonymyWord> sywList = synonymyWordDao.retrieveList(param);
		List<String> allWord = new ArrayList<>();
		for (SynonymyWord syw : sywList) {
			if (!allWord.contains(syw.getWord())) {
				allWord.add(syw.getWord());
			}
		}
		// 判断需要替换的正则
		Pattern p = Pattern.compile("[\\dIVX一二三四五六七八九十壹贰叁肆伍陆柒捌玖拾]+[-]*[\\dIVX一二三四五六七八九十壹贰叁肆伍陆柒捌玖拾]*[期级度°型]");
		Pattern p2 = Pattern.compile("[ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ]+[期级度°型]");
		Map<String, Synonymy> stdAndSy = new HashMap<>();
		// 判断是否存在需要替换的罗马字符的同义词
		for (Synonymy sy : syList) {
			String words = sy.getWords();
			Matcher m = p.matcher(words);
			String[] wordArr = words.substring(1, words.length()).split("\t");
			for (String word : wordArr) {
				if ("急性淋巴细胞性白血病，L1型".equals(word)) {
					System.out.println(1111);
				}
			}
			if (m.find()) {
				String std = "";
				// 如果标准词是罗马字符就不需要修改
				Matcher m4 = p2.matcher(sy.getStd());
				if (m4.find()) {
					// 全部转成罗马字符放入map
					for (String word : wordArr) {
						word = getStringToRoman(word);
						stdAndSy.put(word, sy);
					}
				} else {
					// 有需要替换的同义词,判断是否该同义词组中就含有罗马字符的同义词,设置为标准词
					for (String word : wordArr) {
						Matcher m2 = p2.matcher(words);
						if (m2.find()) {
							std = getStringToRoman(word);
							break;
						}
					}
					if (StringUtils.isNotBlank(std)) {
						String reg = "^[u0391-uFFE5/!@#$%^&*()_+-=,./;\\<>?:{}|`~]*$";
						sy.setStd(std);
						if (std.matches(reg)) {
							sy.setEnglishStd(std);
							sy.setChineseStd("");
						} else {
							sy.setEnglishStd("");
							sy.setChineseStd(std);
						}
						sy.setModifierName("系统管理员");
						sy.setModifierId(1L);
						synonymyDao.update(sy);
						stdAndSy.put(std, sy);
						for (String word : wordArr) {
							word = getStringToRoman(word);
							stdAndSy.put(word, sy);
						}
					} else {
						// 没有则需要新增罗马字符的同义词并设置为标准词
						for (String word : wordArr) {
							Matcher m3 = p.matcher(words);
							if (m3.find()) {
								std = word;
								break;
							}
						}
						std = getStringToRoman(std);
						if (!allWord.contains(std)) {
							// 新增同义词的标准词
							String reg = "^[u0391-uFFE5/!@#$%^&*()_+-=,./;\\<>?:{}|`~]*$";
							sy.setStd(std);
							if (std.matches(reg)) {
								sy.setEnglishStd(std);
								sy.setChineseStd(sy.getChineseStd());
							} else {
								sy.setEnglishStd(sy.getEnglishStd());
								sy.setChineseStd(std);
							}
							sy.setWords(sy.getWords() + std + "\t");
							sy.setModifierName("系统管理员");
							sy.setModifierId(1L);
							synonymyDao.update(sy);
							stdAndSy.put(std, sy);
							for (String word : wordArr) {
								word = getStringToRoman(word);
								stdAndSy.put(word, sy);
							}
							SynonymyWord syw = new SynonymyWord();
							syw.setModifierId(1L);
							syw.setProperty("di");
							syw.setSynonymyId(sy.getId());
							syw.setType(1);
							syw.setWord(std);
							syw.setModifierName("系统管理员");
							synonymyWordDao.insert(syw);
							allWord.add(std);
						}
					}
				}
			}
		}

		// 获取所有的疾病名称,判断是否可以转成罗马字符
		List<String> allDiseaseName = icdDiseaseHospitalDao.retrieveAllDiseaseName();
		for (String diseaseName : allDiseaseName) {
			diseaseName = changeStr(diseaseName);
			Matcher m = p.matcher(diseaseName);
			if (m.find()) {
				String romanDiseaseName = getStringToRoman(diseaseName);
				// 查询同义词中是否已经存在罗马字符的同义词
				if (stdAndSy.get(romanDiseaseName) == null) {
					// 新增一组同义词
					Synonymy synonymy = new Synonymy();
					String reg = "^[u0391-uFFE5/!@#$%^&*()_+-=,./;\\<>?:{}|`~]*$";
					synonymy.setStd(romanDiseaseName);
					if (romanDiseaseName.matches(reg)) {
						synonymy.setEnglishStd(romanDiseaseName);
						synonymy.setChineseStd("");
					} else {
						synonymy.setEnglishStd("");
						synonymy.setChineseStd(romanDiseaseName);
					}
					synonymy.setWords("\t" + romanDiseaseName + "\t" + diseaseName + "\t");
					synonymy.setProperty("di");
					synonymy.setType(1);
					synonymy.setModifierId(1L);
					synonymy.setModifierName("系统管理员");
					long synonymyId = synonymyDao.insert(synonymy);
					List<String> wordList = new ArrayList<>();
					wordList.add(romanDiseaseName);
					wordList.add(diseaseName);
					User user = new User();
					user.setUserId(1L);
					user.setRealName("系统管理员");
					synonymyWordDao.batchInsert(synonymyId, wordList, user, 1, "di");
					// 新增的加入map
					stdAndSy.put(romanDiseaseName, synonymy);
				} else {
					if (!allWord.contains(diseaseName)) {
						// 新增入该组同义词
						Synonymy sy = stdAndSy.get(romanDiseaseName);
						sy.setWords(sy.getWords() + diseaseName + "\t");
						synonymyDao.update(sy);
						SynonymyWord syw = new SynonymyWord();
						syw.setModifierId(1L);
						syw.setProperty("di");
						syw.setSynonymyId(sy.getId());
						syw.setType(1);
						syw.setWord(diseaseName);
						syw.setModifierName("系统管理员");
						synonymyWordDao.insert(syw);
						allWord.add(diseaseName);
					}
				}
			}
		}
		// 初始化疾病名
		icdDiseaseHospitalDao.initHospitalDiseaseStdDisable2();
	}

	/**
	 * 疾病名转罗马字符
	 * 
	 * @param word
	 * @return
	 */
	private String getStringToRoman(String word) {
		Pattern p = Pattern.compile("[\\dIVX一二三四五六七八九十壹贰叁肆伍陆柒捌玖拾]+[-]?[\\dIVX一二三四五六七八九十壹贰叁肆伍陆柒捌玖拾]*[期级度°型]");
		Matcher m = p.matcher(word);
		while (m.find()) {
			String replacedWord = replaceWord(m.group());
			word = word.replace(m.group(), replacedWord);
		}
		return word;
	}

	private Map<String, String> getReplaceMap() {
		Map<String, String> replaceMap = new LinkedHashMap<>();
		replaceMap.put("1", "Ⅰ");
		replaceMap.put("2", "Ⅱ");
		replaceMap.put("3", "Ⅲ");
		replaceMap.put("4", "Ⅳ");
		replaceMap.put("5", "Ⅴ");
		replaceMap.put("6", "Ⅵ");
		replaceMap.put("7", "Ⅶ");
		replaceMap.put("8", "Ⅷ");
		replaceMap.put("9", "Ⅸ");
		replaceMap.put("10", "Ⅹ");
		replaceMap.put("11", "Ⅺ");
		replaceMap.put("12", "Ⅻ");
		replaceMap.put("一", "Ⅰ");
		replaceMap.put("二", "Ⅱ");
		replaceMap.put("三", "Ⅲ");
		replaceMap.put("四", "Ⅳ");
		replaceMap.put("五", "Ⅴ");
		replaceMap.put("六", "Ⅵ");
		replaceMap.put("七", "Ⅶ");
		replaceMap.put("八", "Ⅷ");
		replaceMap.put("九", "Ⅸ");
		replaceMap.put("十", "Ⅹ");
		replaceMap.put("十一", "Ⅺ");
		replaceMap.put("十二", "Ⅻ");
		replaceMap.put("壹", "Ⅰ");
		replaceMap.put("贰", "Ⅱ");
		replaceMap.put("叁", "Ⅲ");
		replaceMap.put("肆", "Ⅳ");
		replaceMap.put("伍", "Ⅴ");
		replaceMap.put("陆", "Ⅵ");
		replaceMap.put("柒", "Ⅶ");
		replaceMap.put("捌", "Ⅷ");
		replaceMap.put("玖", "Ⅸ");
		replaceMap.put("拾", "Ⅹ");
		replaceMap.put("拾壹", "Ⅺ");
		replaceMap.put("拾贰", "Ⅻ");
		replaceMap.put("XII", "Ⅻ");
		replaceMap.put("XI", "Ⅺ");
		replaceMap.put("IX", "Ⅸ");
		replaceMap.put("X", "Ⅹ");
		replaceMap.put("VIII", "Ⅷ");
		replaceMap.put("VII", "Ⅶ");
		replaceMap.put("VI", "Ⅵ");
		replaceMap.put("IV", "Ⅳ");
		replaceMap.put("V", "Ⅴ");
		replaceMap.put("III", "Ⅲ");
		replaceMap.put("II", "Ⅱ");
		replaceMap.put("I", "Ⅰ");
		replaceMap.put("---", "-");
		replaceMap.put("--", "-");
		replaceMap.put("ⅠⅠⅠ", "Ⅲ");
		replaceMap.put("ⅠⅠ", "Ⅱ");

		return replaceMap;
	}

	private String replaceWord(String word) {
		Map<String, String> replaceMap = getReplaceMap();
		Iterator<Map.Entry<String, String>> it = replaceMap.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry<String, String> entry = it.next();
			if (word.indexOf(entry.getKey()) > -1) {
				word = word.replace(entry.getKey(), entry.getValue());
			}
		}
		return word;
	}
}
